/**
 * 身份证验证工具类
 * 包含格式验证、校验位验证、地区验证、出生日期验证等功能
 */

class IdCardValidator {
  constructor() {
    // 身份证前6位地区码映射（示例，实际应用中需要完整的地区码表）
    this.areaCodeMap = {
      '11': '北京', '12': '天津', '13': '河北', '14': '山西', '15': '内蒙古',
      '21': '辽宁', '22': '吉林', '23': '黑龙江', '31': '上海', '32': '江苏',
      '33': '浙江', '34': '安徽', '35': '福建', '36': '江西', '37': '山东',
      '41': '河南', '42': '湖北', '43': '湖南', '44': '广东', '45': '广西',
      '46': '海南', '50': '重庆', '51': '四川', '52': '贵州', '53': '云南',
      '54': '西藏', '61': '陕西', '62': '甘肃', '63': '青海', '64': '宁夏',
      '65': '新疆', '71': '台湾', '81': '香港', '82': '澳门', '91': '国外'
    };
    
    // 身份证加权因子
    this.weightFactor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
    
    // 身份证校验码映射
    this.checkCodeMap = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
  }

  /**
   * 验证身份证号码是否有效
   * @param {string} idCard - 身份证号码
   * @returns {object} - 验证结果 {valid: boolean, message: string, info: object}
   */
  validate(idCard) {
    if (!idCard) {
      return { valid: false, message: '身份证号码不能为空' };
    }

    // 去除空格并转为大写
    idCard = idCard.trim().toUpperCase();

    // 基本格式验证
    if (!this.checkFormat(idCard)) {
      return { valid: false, message: '身份证号码格式不正确，只能包含数字或X' };
    }

    // 长度验证
    if (idCard.length !== 15 && idCard.length !== 18) {
      return { valid: false, message: '身份证号码长度必须为15位或18位，当前长度为' + idCard.length };
    }

    // 15位身份证验证
    if (idCard.length === 15) {
      return this.validate15Bit(idCard);
    }

    // 18位身份证验证
    return this.validate18Bit(idCard);
  }

  /**
   * 验证身份证号码格式
   * @param {string} idCard - 身份证号码
   * @returns {boolean}
   */
  checkFormat(idCard) {
    const regex15 = /^\d{15}$/;
    const regex18 = /^\d{17}[\dX]$/;
    return regex15.test(idCard) || regex18.test(idCard);
  }

  /**
   * 验证15位身份证号码
   * @param {string} idCard - 15位身份证号码
   * @returns {object} - 验证结果
   */
  validate15Bit(idCard) {
    const year = idCard.substring(6, 8);
    const month = idCard.substring(8, 10);
    const day = idCard.substring(10, 12);

    // 验证出生日期
    if (!this.isValidDate('19' + year, month, day)) {
      return { valid: false, message: '出生日期无效：' + month + '月' + day + '日不存在' };
    }

    // 验证地区码
    const areaCode = idCard.substring(0, 2);
    if (!this.areaCodeMap[areaCode]) {
      return { valid: false, message: '地区码无效：' + areaCode + '不是有效的行政区划代码' };
    }

    return {
      valid: true,
      message: '15位身份证号码有效',
      info: {
        type: '15位',
        area: this.areaCodeMap[areaCode],
        birth: `19${year}-${month}-${day}`,
        gender: parseInt(idCard.substring(14, 15)) % 2 === 1 ? '男' : '女'
      }
    };
  }

  /**
   * 验证18位身份证号码
   * @param {string} idCard - 18位身份证号码
   * @returns {object} - 验证结果
   */
  validate18Bit(idCard) {
    const year = idCard.substring(6, 10);
    const month = idCard.substring(10, 12);
    const day = idCard.substring(12, 14);

    // 验证出生日期
    if (!this.isValidDate(year, month, day)) {
      return { valid: false, message: '出生日期无效：' + year + '年' + month + '月' + day + '日不存在' };
    }

    // 验证地区码
    const areaCode = idCard.substring(0, 2);
    if (!this.areaCodeMap[areaCode]) {
      return { valid: false, message: '地区码无效：' + areaCode + '不是有效的行政区划代码' };
    }

    // 验证校验位
    if (!this.checkVerifyCode(idCard)) {
      return { valid: false, message: '身份证校验位错误：第18位校验码不正确' };
    }

    const age = this.calculateAge(year, month, day);
    if (age < 18) {
      return { valid: false, message: '年龄不符合要求：必须年满18周岁' };
    }

    return {
      valid: true,
      message: '18位身份证号码有效',
      info: {
        type: '18位',
        area: this.areaCodeMap[areaCode],
        birth: `${year}-${month}-${day}`,
        gender: parseInt(idCard.substring(16, 17)) % 2 === 1 ? '男' : '女',
        age: age
      }
    };
  }

  /**
   * 验证校验位
   * @param {string} idCard - 18位身份证号码
   * @returns {boolean}
   */
  checkVerifyCode(idCard) {
    const idCardArray = idCard.split('');
    let sum = 0;

    for (let i = 0; i < 17; i++) {
      if (!/\d/.test(idCardArray[i])) {
        return false;
      }
      sum += parseInt(idCardArray[i]) * this.weightFactor[i];
    }

    const remainder = sum % 11;
    const verifyCode = this.checkCodeMap[remainder];

    return verifyCode === idCardArray[17];
  }

  /**
   * 验证日期是否有效
   * @param {string} year - 年
   * @param {string} month - 月
   * @param {string} day - 日
   * @returns {boolean}
   */
  isValidDate(year, month, day) {
    const y = parseInt(year);
    const m = parseInt(month);
    const d = parseInt(day);

    if (y < 1900 || y > new Date().getFullYear()) {
      return false;
    }

    if (m < 1 || m > 12) {
      return false;
    }

    const daysInMonth = new Date(y, m, 0).getDate();
    return d >= 1 && d <= daysInMonth;
  }

  /**
   * 计算年龄
   * @param {string} year - 出生年
   * @param {string} month - 出生月
   * @param {string} day - 出生日
   * @returns {number} - 年龄
   */
  calculateAge(year, month, day) {
    const birthDate = new Date(`${year}-${month}-${day}`);
    const today = new Date();
    let age = today.getFullYear() - birthDate.getFullYear();
    
    const monthDiff = today.getMonth() - birthDate.getMonth();
    if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
      age--;
    }
    
    return age;
  }

  /**
   * 15位身份证转18位
   * @param {string} idCard15 - 15位身份证号码
   * @returns {string} - 18位身份证号码
   */
  convert15To18(idCard15) {
    if (idCard15.length !== 15) {
      throw new Error('输入必须是15位身份证号码');
    }

    let idCard18 = idCard15.substring(0, 6) + '19' + idCard15.substring(6);
    
    const idCardArray = idCard18.split('');
    let sum = 0;

    for (let i = 0; i < 17; i++) {
      sum += parseInt(idCardArray[i]) * this.weightFactor[i];
    }

    const remainder = sum % 11;
    const verifyCode = this.checkCodeMap[remainder];

    return idCard18 + verifyCode;
  }

  /**
   * 获取身份证信息
   * @param {string} idCard - 身份证号码
   * @returns {object} - 身份证信息
   */
  getInfo(idCard) {
    const result = this.validate(idCard);
    if (result.valid) {
      return result.info;
    }
    return null;
  }

  /**
   * 快速验证身份证号码格式
   * @param {string} idCard - 身份证号码
   * @returns {boolean} - 格式是否正确
   */
  isValidFormat(idCard) {
    if (!idCard) return false;
    idCard = idCard.trim().toUpperCase();
    const regex15 = /^\d{15}$/;
    const regex18 = /^\d{17}[\dX]$/;
    return regex15.test(idCard) || regex18.test(idCard);
  }
}

// 创建单例实例
const idCardValidator = new IdCardValidator();

// 导出验证函数
export function validateIdCard(idCard) {
  return idCardValidator.validate(idCard);
}

export function getIdCardInfo(idCard) {
  return idCardValidator.getInfo(idCard);
}

export function convert15To18(idCard15) {
  return idCardValidator.convert15To18(idCard15);
}

export function isValidIdCardFormat(idCard) {
  return idCardValidator.isValidFormat(idCard);
}

// 默认导出验证器实例
export default idCardValidator;